home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Topik / Topik - Disk 08 - TOPIKless (19xx)(Topik Public Domain)(PD)[WB].zip / Topik - Disk 08 - TOPIKless (19xx)(Topik Public Domain)(PD)[WB].adf / A68k / a68k.doc < prev    next >
Text File  |  1989-07-09  |  26KB  |  541 lines

  1.  
  2. *** TOPIK Note - Don't Panic, its here ! Best used from a CLI environment,
  3. A68k is in this directory under that name.
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.    A68k - a freely   distributable assembler   for the   Amiga
  11.  
  12.          by Charlie Gibbs
  13.  
  14.            with special thanks to
  15.       Brian R. Anderson and Jeff Lydiatt
  16.  
  17.        (Version 2.41 - January 6, 1989)
  18.  
  19.      Note:  This program is Freely-Distributable, as opposed to   Public
  20. Domain.    Permission is given to   freely distribute this program provided   no
  21. fee is charged,   and this documentation file is included   with the program.
  22.  
  23.      This assembler is based on   Brian R. Anderson's 68000 cross-
  24. assembler published in Dr. Dobb's Journal, April through June 1986.
  25. I have converted it to produce AmigaDOS-format object modules, and
  26. have made many enhancements, such as macros and   INCLUDE   files.
  27.  
  28.      My   first step was to convert the original Modula-2   code into C.
  29. I did this for two reasons.  First, I had access to a C   compiler, but
  30. not a Modula-2 compiler.  Second, I like C better anyway.
  31.  
  32.      The executable code generator code   (GetObjectCode and MergeModes)
  33. is essentially the same   as in the original article, aside from its
  34. translation into C.  I have almost completely rewritten   the remainder
  35. of the code, however, in order to remove restrictions, add enhancements,
  36. and adapt it to   the AmigaDOS environment.  Since the only reference book
  37. available to me   was the   AmigaDOS Developer's Manual (Bantam, February
  38. 1986), the assembler and the remainder of this document   work in   terms
  39. of that   book.
  40.  
  41.  
  42. RESTRICTIONS
  43.  
  44.      Let's get these out of the way first.  There are a few things that I
  45. have not yet implemented, and some outright bugs that would take too long
  46. to correct for this version.
  47.  
  48.       o   The verification file (-v) option is not supported.  Diagnostic
  49.    messages always   appear on the console.   They also appear in the
  50.    listing   file, however (see extensions below).  You can produce
  51.    an error file by redirecting console output to a file -   the
  52.    line number counter and   final summary are displayed on stderr
  53.    so you can still see what's happening.
  54.  
  55.       o   The file names in the INCLUDE directory   list (-i) must be separated
  56.    by commas.  The   list may not be   enclosed in quotes.
  57.  
  58.       o   Labels assigned   by EQUR   and REG   directives are case-sensitive.
  59.  
  60.       o   The following directives are not supported, and   will be   flagged   as
  61.    invalid   op-codes:
  62.  
  63.       OFFSET
  64.       NOPAGE
  65.       LLEN
  66.       PLEN
  67.       NOOBJ
  68.       FAIL
  69.       FORMAT
  70.       NOFORMAT
  71.       MASK2
  72.  
  73.    I feel that NOPAGE, LLEN, and PLEN should not be defined within   a
  74.    source module.   It doesn't make sense to me to have to change your
  75.    program   just because you want to print your listings on   different
  76.    paper.   The command-line option   "-p" (see below) can be used as a
  77.    replacement for   PLEN; setting it to a high value (like 32767) is a
  78.    good substitute   for NOPAGE.  The effect   of LLEN   can be obtained
  79.    by running the listing file through an appropriate filter.
  80.  
  81.  
  82. EXTENSIONS
  83.  
  84.      Now for the good stuff:
  85.  
  86.       o   Labels can be any length that will fit onto one   source line
  87.    (currently 127 bytes maximum).   Since labels are stored   on the
  88.    heap, the number of labels that   can be processed is limited only
  89.    by available memory.
  90.  
  91.       o   Since section data and user macro definitions are stored in the
  92.    symbol table (see above), they too are limited only by available
  93.    memory.    (Actually, there is a hard-coded limit   of 32767 sections,
  94.    but I doubt anyone will   run into that one.)
  95.  
  96.       o   The only values   a label   cannot take are   the register names - the
  97.    assembler can distinguish between the same name   used as   a label,
  98.    instruction name or directive, macro name, or section name.
  99.  
  100.       o   Section   and user macro names appear in the symbol table   dump, and
  101.    will also be cross-referenced.   Their names can   be the same as any
  102.    label (see above); the assembler can sort them out.
  103.  
  104.       o   INCLUDEs and macro calls can be   nested indefinitely, limited only
  105.    by available memory.  The message "Secondary heap overflow -
  106.    assembly terminated" will be displayed if memory is exhausted.
  107.    You can   increase the size of this heap using the -w parameter
  108.    (see below).  Recursive   macros are supported; recursive   INCLUDEs
  109.    will, of course, result   in a loop that will be broken only when
  110.    the heap overflows.
  111.  
  112.       o   The EVEN directive forces alignment on a word (2-byte) boundary.
  113.    It does   the same thing as CNOP 0,2.
  114.    (This one is left over from the   original code.)
  115.  
  116.       o   Branch (Bcc) instructions to a previously-defined label   will be
  117.    automatically converted   to short form if possible.  This feature is
  118.    not available for forward branches, since in pass 1 the   assembler
  119.    doesn't yet know how far the branch must go.  You can, however,
  120.    ask A68k to tell you which instructions   can be coded as   short
  121.    branches by using the -f command-line switch (see below).
  122.  
  123.       o   Backward references to labels within the current CODE section
  124.    will be   converted to PC   relative addressing with displacement
  125.    if this   mode is   legal for the instruction.
  126.  
  127.       o   If a MOVEM instruction only specifies one register, it is converted
  128.    to the corresponding MOVE instruction.   Instructions such as
  129.    MOVEM D0-D0,label will not be converted, however.
  130.  
  131.       o   ADD, SUB, and MOVE instructions   will be   converted to ADDQ, SUBQ,
  132.    and MOVEQ respectively if possible.  Instructions coded   explicitly
  133.    as (for   example) ADDA or ADDI will not be converted.
  134.  
  135.       o   ADD, CMP, SUB, and MOVE   to an address register are converted to
  136.    ADDA, CMPA, SUBA, and MOVEA respectively, unless (for ADD, SUB,
  137.    or MOVE) they have already been   converted to quick form.
  138.  
  139.       o   ADD, AND, CMP, EOR, OR,   and SUB   of an immediate   value are converted
  140.    to ADDI, ANDI, CMPI, EORI, ORI,   and SUBI respectively (unless the
  141.    address   register or quick conversion above has already been done).
  142.  
  143.       o   If both   operands of a CMP instruction are postincrement   mode, the
  144.    instruction is converted to CMPM.
  145.  
  146.       o   Operands of the   form 0(An) will   be treated as (An) except for
  147.    the MOVEP instruction, which always requires a displacement.
  148.  
  149.       o   The SECTION directive allows a third parameter.    This can be
  150.    specified as either CHIP or FAST (upper- or lower-case).  If this
  151.    parameter is present, the hunk will be written with the   MEMF_CHIP
  152.    or MEMF_FAST bit set.  This allows you to produce "pre-ATOMized"
  153.    object modules.
  154.  
  155.       o   The synonyms DATA and BSS are accepted for SECTION directives
  156.    starting data or BSS hunks.  The CHIP and FAST options mentioned
  157.    above can also be used,   e.g. BSS name,CHIP.
  158.  
  159.       o   The following synonyms have been implemented for compatibility
  160.    with the Aztec assembler:
  161.       CSEG is   treated   the same as CODE or SECTION name,CODE
  162.       DSEG is   treated   the same as DATA or SECTION name,DATA
  163.       PUBLIC is treated as either XDEF or XREF, depending on
  164.           whether or not the symbol in question has been
  165.           defined in the current source module.
  166.           A single PUBLIC directive can name a mixture
  167.           internally-   and externally-defined symbols.
  168.  
  169.       o   The ability to produce Motorola   S-records is retained from the
  170.    original code.   The -s option causes the assembler to produce
  171.    S-format instead of AmigaDOS format.  Relocatable code cannot be
  172.    produced in this format.
  173.  
  174.       o   Error messages consist of three   parts.
  175.        The   position of the   offending line is given   as a line number
  176.    within the current module.  If the line   is within a macro expan-
  177.    sion or   INCLUDE   file, the position of the macro   call or   INCLUDE
  178.    statement in the outer module is given as well.    This process
  179.    is repeated until the outermost   source module is reached.
  180.        Next, the offending   source line itself is listed.
  181.        Finally, the errors   for that line are displayed.  A   flag
  182.    (^) is placed under the   column where the error was detected.
  183.  
  184.       o   Named local labels are supported.  These work the same as the
  185.    local labels supported by the Metacomco   assembler (nnn$) but
  186.    can be formed in the same manner as normal labels, except that
  187.    the first character must be a backslash   (\).
  188.  
  189.       o   The following synonyms have been implemented for compatibility
  190.    with the Assempro assembler:
  191.       ENDIF is treated the same as ENDC
  192.       = is treated the same as EQU
  193.       | is treated the same as ! (logical OR)
  194.  
  195.       o   Quotation marks   (") can be used as string delimiters
  196.    as well   as apostrophes (').  Any given string must begin
  197.    and end   with the same delimiter.  This allows such statements
  198.    as the following:
  199.       MOVEQ   '"',D0
  200.       DC.B   "This is Charlie's assembler."
  201.    Note that you can still   define an apostrophe within a string
  202.    delimited by apostrophes if you   double it, e.g.
  203.       MOVEQ   '''',D0
  204.       DC.B   'This is Charlie''s assembler.'
  205.  
  206.       o   If any errors are found   in the assembly, the object code file
  207.    will be   scratched, unless you specified   the -k (keep) flag
  208.    on the command line.
  209.  
  210.       o   The symbols .A68K, .a68k, .a68K, and .A68k are automatically
  211.    defined   as SET symbols having absolute values of 1.
  212.    This enables a source program to determine whether it is
  213.    being assembled   by this   assembler, and is effectively
  214.    insensitive as to whether or not it is checked in upper   case.
  215.  
  216.       o   A zeroth positional macro parameter (\0) is supported.   It
  217.    is replaced by the length of the macro call (B,   W, or L,
  218.    defaulting to W).  For instance, given the macro:
  219.       moov   MACRO
  220.          move.\0   \1,\2
  221.          ENDM
  222.    the macro call
  223.          moov.l   d0,d1
  224.    would be expanded as
  225.          move.l   d0,d1
  226.  
  227.       o   If an INCLUDE file doesn't generate any code and no listing
  228.    file is   required (including suppression   of the listing using
  229.    NOLIST), it won't be read again in pass 2.  The statement
  230.    numbers   will be   bumped to keep in proper alignment.  This
  231.    can really speed up assemblies that INCLUDE lots of EQUates.
  232.  
  233.       o   The ORG   directive is supported.    It works like RORG, except
  234.    that it   takes the actual address to be jumped to, rather
  235.    than an   offset from the   start of the current section.
  236.    The given address must be in the current section.
  237.    As far as A68k is concerned, the only real difference
  238.    between   ORG and   RORG is   that the ORG value must   be
  239.    relocatable, while the RORG value must be absolute.
  240.  
  241.  
  242. THE SMALL CODE / SMALL DATA MODEL
  243.  
  244.      Version 2.4 implements a rudimentary small   code/data model.
  245. It consists of converting any data reference to   one of the following
  246. three addressing modes:
  247.    address   register indirect with displacement (using A4)
  248.       (for references   to the DATA or BSS section)
  249.    program   counter   indirect with displacement
  250.       (for references   to the CODE section)
  251.    absolute word
  252.       (for absolute and 16-bit relocatable values)
  253. These conversions do not take place unless a NEAR directive is
  254. encountered.  Any operands on the NEAR directive are ignored.
  255. Conversion is done for all operands until a FAR   directive is
  256. encountered.  NEAR and FAR directives can occur   any number of
  257. times, enabling   conversion to be turned   on and off at will.
  258.  
  259.      Backward references which cannot be converted (e.g. external
  260. labels declared   as XREF) will remain as   absolute long addressing.
  261. All forward references are assumed to be convertible, since during
  262. pass 1 A68k has   no way of telling whether conversion is   possible.
  263. If conversion turns out   to be impossible, invalid object code will
  264. be generated - an error   message   ("Invalid forward reference") will
  265. indicate when this occurs.
  266.  
  267.      Although the small   code/data model   can greatly reduce the
  268. size of   assembled programs, several restrictions apply:
  269.  
  270.       o   Small code and small data models are active simultaneously.
  271.    You can't have one without the other, since during pass 1
  272.    A68k doesn't know whether forward references are to CODE
  273.    or to DATA/BSS.
  274.  
  275.       o   Programs can consist of   a maximum of two sections,
  276.    one CODE, the other DATA or BSS.  If you try to   define
  277.    a third   section, the message "Too many SECTIONs" will
  278.    be displayed.  The NEAR   directive is active only within
  279.    the CODE section.
  280.  
  281.       o   While the NEAR directive is active, external labels (XREF)
  282.    must be   declared before   they are used, CODE section references
  283.    must be   with 32K of the   current   position (i.e. expressible as
  284.    PC-relative), and DATA/BSS section references must be in the
  285.    first 64K of the DATA/BSS section (i.e.   expressible as
  286.    address   register indirect with displacement).  Any instructions
  287.    which do not satisfy these requirements   cannot be detected in
  288.    pass 1,   so A68k   has no choice but to display an   error message
  289.    in pass   2 ("Invalid forward reference") which in this case
  290.    indicates that invalid code has   been generated.    To properly
  291.    assemble such instructions, you   can temporarily   disable
  292.    conversion with   a FAR directive, then resume afterwards
  293.    with another NEAR directive.
  294.  
  295.       o   Conversion cannot be done for references between modules.
  296.    All external references   must be   left as   absolute long.
  297.  
  298.       o   A68k assumes that register A4 points to   the start of the
  299.    DATA/BSS section plus 32768 bytes.  A4 must be preloaded
  300.    with this value   before executing any code converted by the
  301.    NEAR directive.    One way to do this is to code the instruction
  302.    that loads the register   prior to the NEAR directive.  Another
  303.    way is to use a   MOVE.L with immediate mode, which is never
  304.    converted.  Here are examples of the two methods:
  305.  
  306.       LEA   data+32768,a4      NEAR
  307.       NEAR            MOVE.L   #data+32768,a4
  308.        <remainder of code>          <remainder of code>
  309.       BSS            BSS
  310.    data:            data:
  311.        <data areas>          <data areas>
  312.       END            END
  313.  
  314.  
  315. HOW TO USE A68k
  316.  
  317.      The command-line syntax to   run the   assembler is as   follows:
  318.  
  319.    a68k <source file name>
  320.         [<object file name>]
  321.         [<listing file name>]
  322.       [-d]
  323.       [-e<equate file   name>]
  324.       [-f]
  325.       [-h<header file   name>]
  326.       [-i<INCLUDE directory list>]
  327.       [-k]
  328.       [-l<listing file name>]
  329.       [-o<object file>]
  330.       [-p<page depth>]
  331.       [-q[<quiet interval>]]
  332.       [-s]
  333.       [-t]
  334.       [-w[<hash table   size>][,<secondary heap   size>]]
  335.       [-x<listing file name>]
  336.       [-y]
  337.       [-z[<debug start line>][,<debug   end line>]]
  338.  
  339. These options can be given in any order, and the source   file name can
  340. appear before all switches, after them,   or anywhere in the middle.
  341. Option values, if any, must immediately   follow the keyword with
  342. no intervening spaces.
  343.  
  344.      If   the -o keyword is omitted, the object file will   be given a default
  345. name.  It is created by   replacing all characters after the last   period in
  346. the source file   name by   "o".  For example, if the source file name is
  347. "myprog.asm", the object file name defaults to "myprog.o".  A source name
  348. of "my.new.prog.asm" produces a default object file name of "my.new.prog.o".
  349. If the source file name   does not contain a period, ".o" is appended to it
  350. to produce the default object file name.
  351.  
  352.      The default value for the listing file name is arrived at in the same
  353. way as the object file name, except that ".lst" is appended instead of ".o".
  354. If you don't specify this parameter, no listing file will be produced.
  355. If you specify -x (see below), -l (with   the default name) is assumed,
  356. although you can still use this   parameter if you wish.
  357.  
  358.      The default value for the equate file name   is arrived at in the same
  359. way as the object file name, except that ".equ" is appended instead of ".o".
  360.  
  361.      The INCLUDE directory list   is a list of directory names separated by
  362. commas.    No embedded blanks are   allowed.  For example, the specification
  363.    -imylib,df1:another.lib
  364. will cause INCLUDE files to be searched   for first in the current directory,
  365. then in   "mylib", then in "df1:another.lib".
  366.  
  367.      The -d keyword causes symbol table   entries   (hunk_symbol) to be written
  368. to the object module for the use of symbolic debuggers.
  369.  
  370.      The -f keyword causes any forward branches   (Bcc, BRA, BSR)   that
  371. could be converted to short form to be flagged.    A68k can't convert them
  372. automatically because it doesn't know in pass 1 how far the branch will
  373. be.  This option tells you which instructions could be manually   converted.
  374.  
  375.      The -k keyword causes the object file to be kept if any errors were
  376. found.   Otherwise, it will be scratched   if any errors occurred.
  377.  
  378.      The -l keyword causes a listing file to be   produced.  If you want
  379. the listing file to include a symbol table dump   and cross-reference,
  380. use the   -x keyword instead (see   below).
  381.  
  382.      The -p keyword causes the page depth to be   set to the specified value.
  383. If omitted, a default of 60 lines (-p60) is assumed.
  384.  
  385.      The -q keyword changes the   interval at which A68k displays   the
  386. current   line number (the default is every 10 lines, i.e. -q10).    If
  387. you specify -q0   or -q without a   value, no line numbers will be displayed.
  388. This will speed   up assemblies slightly by reducing console I/O.    If -q
  389. is specified as   a negative number (e.g.   -q-10),   line numbers will still
  390. be displayed at   the specified interval,   but will be given as positions
  391. within the current module (source, macro, or INCLUDE) rather than
  392. as a total statement count - the module   name will also be displayed.
  393.  
  394.      The -s keyword, if   specified, causes the object file to be   written   in
  395. Motorola S-record format.  If omitted, AmigaDOS   format will be produced.
  396. The default name for an   S-record file has ".s" appended to the source name,
  397. rather than ".o"; this can still be overridden with the -o keyword, though.
  398.  
  399.      The -t keyword allows tabs   in the source file to be passed   through
  400. to the listing file, rather than being expanded.  In addition, tabs will
  401. be generated in   the listing file to skip from the object code to the
  402. source statement, etc.   This can greatly reduce   the size of the   listing
  403. file, as well as making   it quicker to produce.   Do not use this   option
  404. if you will be displaying or listing the list file on a   device which
  405. does not assume   a tab stop at every 8th   position.
  406.  
  407.      The -w keyword specifies the size of the fixed memory areas that
  408. are allocated.   The first parameter gives the number of   entries   that
  409. the hash table will contain (defaulting   to 2047).  This   should be enough
  410. for all   but the   very largest programs.   The assembly will not fail if
  411. this value is too small, but may slow down as a   result of A68k having
  412. to search many long hash chains.  I've heard that you should really
  413. specify   a prime   number for this   parameter, but I haven't gone into
  414. hashing   theory enough to know whether it's actually necessary.
  415.      The second   parameter of the -w keyword specifies the size of the
  416. secondary heap (defaulting to 1024 bytes, which   should be enough
  417. unless you use very deeply nested macros and/or   INCLUDE   files with long
  418. path names).
  419.      You can specify either or both parameters.    For example:
  420.    -w4093      secondary heap size remains at 1024 bytes
  421.    -w,2000      hash table size   remains   at 2047   entries
  422.    -w4093,2000   increases the size of both areas
  423.      If   you're really tight for memory, and are assembling small modules,
  424. you can   use this keyword to shrink these areas below their default sizes.
  425. At the end of an assembly, a message will be displayed giving the sizes
  426. actually used, in the form of the -w command you would have to enter to
  427. allocate that much space.  This   is primarily useful to see how much
  428. secondary heap space was used.
  429.      NOTE: All other table storage (e.g. the actual symbol table) is
  430. allocated as required (currently in 8K chunks).
  431.  
  432.      The -x keyword works the same as -l, except that a   symbol table
  433. dump, including   cross-reference   information, will be added to the end
  434. of the listing file.
  435.  
  436.      The -y keyword causes hashing statistics to be displayed.   First
  437. the number of symbols in the table is given, followed by a breakdown
  438. of hash   chains by length.  Chains with length zero denote unused hash
  439. table entries.   Ideally   (i.e. if there were no collisions) there should
  440. be as many chains with length 1   as there are symbols, and there   should
  441. be no chains of   length 2 or greater.  I   added this option to help me
  442. tune my   hashing   algorithm, but you can also use   it to see whether you
  443. should allocate   a larger hash table (using the first parameter of the
  444. -w option, see above).
  445.  
  446.      The -z keyword is provided   for debugging purposes.    You can cause
  447. the assembler to list a   range of source   lines, complete   with line number
  448. and current location counter value, during both   passes.    For example:
  449.    -z      lists all source lines
  450.    -z100,200   lists lines 100   through   200
  451.    -z100      lists all lines   starting at 100
  452.    -z,100      lists the first   100 lines
  453.  
  454.  
  455.      If   you wish to override the default object   and (optionally) listing
  456. file names, you   can omit the -o   and -l keywords.  The assembler   interprets
  457. the first three   parameters without leading hyphens as the source, object,
  458. and listing file names respectively.  Anything over three file names is   an
  459. error, as is attempting   to respecify a file name with the -o or   -l keywords.
  460.  
  461.  
  462. TECHNICAL INFORMATION
  463.  
  464.      The actual   symbol table entries (pointed to by the   hash table,
  465. colliding entries are linked together) are stored in 8K   chunks which
  466. are allocated as required.  The   first entry of each chunk is reserved
  467. as a link to the next chunk (or   NULL in   the last chunk)   - this makes
  468. it easy   to find   all the   chunks to free them when we're finished.  All
  469. symbol table entries are stored   in pass   1.  During pass   2, cross-reference
  470. table entries are built   in the same group of chunks, immediately following
  471. the last symbol   table entry.  Additional chunks   will continue to be
  472. linked in if necessary.
  473.  
  474.      Symbol names and macro text are stored in another series of linked
  475. chunks.    These chunks consist of a link   pointer   followed by strings
  476. (terminated by nulls) laid end to end.   Symbols   are independent   entries,
  477. linked from the   corresponding symbol table entry.  Macros are stored as
  478. consecutive strings, one per line - the   end of the macro is indicated by
  479. an ENDM   statement.  If a macro spans two chunks, the last line in the
  480. original chunk is followed by a   newline   character to indicate that the
  481. macro is continued in the next chunk.
  482.  
  483.      Relocation   information is built during pass 2 in yet another series
  484. of linked chunks.  If more than   one chunk is needed to hold one   section's
  485. relocation information,   all additional chunks are released at the end of
  486. the section.
  487.  
  488.      The secondary heap   is built from both ends, and it   grows and shrinks
  489. according to how many macros and INCLUDE files are currently open.  At
  490. all times there   will be   at least one entry on the heap,   for the   original
  491. source code file.  The expression parser also uses the secondary heap to
  492. store its working stacks - this   space is freed as soon as an expression
  493. has been evaluated.
  494.      The bottom   of the heap holds the names of the source code file and
  495. any macro or INCLUDE files that   are currently open.  The full path is
  496. given.   A null string is stored   for user macros.  Macro   arguments are
  497. stored by additional strings, one for each argument in the macro call line.
  498. All strings are   stored in minimum space, similar to the   labels and user
  499. macro text on the primary heap.    File names are   pointed   to by the fixed
  500. table entries (see below) - macro arguments are   accessed by stepping past
  501. the macro name to the desired argument,   unless NARG would be exceeded.
  502.      The fixed portion of the heap is built down from the top.   Each entry
  503. occupies 16 bytes.  Enough information is stored to return to the proper
  504. position in the   outer file once   the current macro or INCLUDE file has been
  505. completely processed.
  506.      The diagram below illustrates the layout of the secondary heap.
  507.  
  508.    Heap2 +   maxheap2 ----------->  ___________________________
  509.                   |              |
  510.                   |     Input   file table     |
  511.    struct InFCtl *InF ---------> |___________________________|
  512.                   |              |
  513.                   |     Parser operator stack     |
  514.    struct OpStack *Ops --------> |___________________________|
  515.                   |              |
  516.                   |     (unused space)     |
  517.    struct TermStack *Term -----> |___________________________|
  518.                   |              |
  519.                   |     Parser term stack     |
  520.    char *NextFNS --------------> |___________________________|
  521.                   |              |
  522.                   |     Input   file name stack     |
  523.    char *Heap2 ----------------> |___________________________|
  524.  
  525.      The "high-water mark" for NextFNS is stored in char *High2,
  526. and the   "low-water mark" (to stretch a metaphor) for InF is stored
  527. in struct InFCtl *LowInF.  These figures are used only to determine
  528. the maximum heap usage.
  529.  
  530.  
  531. AND FINALLY...
  532.  
  533.      Please send me any   bug reports, flames, etc.  I can be reached
  534. on Mind   Link (604/533-2312), at   any Panorama (PAcific NORthwest   AMiga
  535. Association) meeting, or via Jeff Lydiatt or Larry Phillips.
  536. (I don't have the time or money to live on Usenet or CompuServe, etc.)
  537.  
  538.             Charlie   Gibbs
  539.             2121 Rindall Avenue
  540.             Port Coquitlam,   B.C.  V3C 1T9
  541.